#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>


#include "sans.h"
#include "garbagecollector.h"
#include "runtime.h"

sdata bltn_string_ref(sdata ob, sdata idx) {
  sdata len;
  
  if (ob.tag != tstrn) {
    log_err("runtime/bltn_string_ref: ob not a string\n");
  }
  
  if (idx.tag != tnumb) {
    log_err("runtime/bltn_string_ref: idx not a number\n");
  }
  
  if (idx.data.ivalue < 0) {
    log_err("runtime/bltn_string_ref: idx is negative\n");
  }
  
  len = heap_ref(ob.data.value);
  
  if (len.tag != tnumb) {
    log_err("runtime/bltn_string_ref: corruption! string length not a number\n");
  }
  
  if (idx.data.ivalue >= len.data.ivalue) {
    log_err("runtime/bltn_string_ref: idx %ld is out of bounds %ld\n", idx.data.ivalue, len.data.ivalue);
  }
  
  return heap_ref(ob.data.value + 1 + idx.data.ivalue);
}

sdata bltn_string_set_bang(sdata ob, sdata idx, sdata val) {
  sdata len;
  
  if (ob.tag != tstrn) {
    log_err("runtime/bltn_string_set: ob not a string\n");
  }
  
  if (idx.tag != tnumb) {
    log_err("runtime/bltn_string_set: idx not a number\n");
  }
  
  if (idx.data.ivalue < 0) {
    log_err("runtime/bltn_string_set: idx is negative\n");
  }
  
  len = heap_ref(ob.data.value);
  
  if (len.tag != tnumb) {
    log_err("runtime/bltn_string_set: corruption! string length not a number\n");
  }
  
  if (idx.data.ivalue >= len.data.ivalue) {
    log_err("runtime/bltn_string_set: idx %ld is out of bounds %ld\n", idx.data.ivalue, len.data.ivalue);
  }
  
  heap_set(ob.data.value + 1 + idx.data.ivalue, val);
  return SDBOOL(0);
}

sdata bltn_string_length(sdata ob) {
  if (ob.tag != tstrn) {
    log_err("runtime/bltn_string_set: ob not a string\n");
  }
  
  return heap_ref(ob.data.value);
}
